package com.sdk.cachesdk.service;

import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service("localCache")
public class LocalCacheServiceImpl implements CacheService {

    private final Map<String, CacheEntry> cache = new HashMap<>();

    @Override
    public void set(String key, Object value) {
        set(key, value, -1);
    }

    @Override
    public void set(String key, Object value, long ttl) {
        if (ttl > 0) {
            long expireTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ttl);
            cache.put(key, new CacheEntry(value, expireTime));
        } else {
            cache.put(key, new CacheEntry(value, -1L));
        }
    }

    @Override
    public <T> T get(String key, Class<T> type) {
        CacheEntry entry = cache.get(key);
        if (entry == null || isExpired(entry)) {
            return null;
        }
        return type.cast(entry.getValue());
    }

    @Override
    public boolean delete(String key) {
        return cache.remove(key) != null;
    }

    @Override
    public boolean hasKey(String key) {
        CacheEntry entry = cache.get(key);
        return entry != null && !isExpired(entry);
    }

    @Override
    public boolean expire(String key, long ttl) {
        CacheEntry entry = cache.get(key);
        if (entry == null) {
            return false;
        }
        long expireTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ttl);
        cache.put(key, new CacheEntry(entry.getValue(), expireTime));
        return true;
    }

    private boolean isExpired(CacheEntry entry) {
        return entry.getExpireTime() >= 0 && entry.getExpireTime() <= System.currentTimeMillis();
    }

    private static class CacheEntry {
        private final Object value;
        private final long expireTime;

        public CacheEntry(Object value, long expireTime) {
            this.value = value;
            this.expireTime = expireTime;
        }

        public Object getValue() {
            return value;
        }

        public long getExpireTime() {
            return expireTime;
        }
    }
}